package com.kk.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.kk.bean.AlipayProps;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@Log4j2
public class AlipayTest {

    @Autowired
    private AlipayProps alipay;

    @GetMapping("")
    public ModelAndView index() {
        return new ModelAndView("alipayTest");
    }

    //支付
    @GetMapping("/pay")
    public String pay(HttpServletResponse httpResponse) {
        Map<String, String> payee = alipay.getPayee();
        AlipayClient alipayClient = new DefaultAlipayClient(
                payee.get("url"),   //支付接口
                payee.get("appid"),            //APPID   支付宝参数
                payee.get("private_key"),      //商家私有密钥
                payee.get("format"),                                    //数据格式
                payee.get("charset"),                                   //数据编码
                payee.get("alipay_key"),       //支付宝提供的公钥
                payee.get("sign_type")); //获得初始化的AlipayClient          //支付加密方式
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request
        alipayRequest.setReturnUrl(payee.get("return_url")); //支付成功后返回页面
        alipayRequest.setNotifyUrl(payee.get("notify_url"));//在公共参数中设置回跳和通知地址
        //保存参数插入
        Map<String, String> map = new LinkedHashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String day = sdf.format(new Date());
        String out_trade_no = day + "000" + (int)Math.ceil(Math.random()*1000);
        log.info("交易订单号out_trade_no：{}", out_trade_no);
        map.put("out_trade_no", out_trade_no);
        map.put("product_code", "FAST_INSTANT_TRADE_PAY");
        map.put("total_amount", "0.02");
        map.put("subject", "测试");
        map.put("body", "测试");

        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(map));

        alipayRequest.setBizContent(jsonObject.toString());//填充业务参数
        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        httpResponse.setContentType("text/html;charset=" + "UTF-8");
        try {
            httpResponse.getWriter().write(form);
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    public static void main(String[] args){
        for (int i = 0; i < 10; i++) {
            System.out.println((int)Math.ceil(Math.random()*1000));
        }
    }

    //退款
    @GetMapping("/refund")
    public void refund(String out_trade_no, String trade_no) {
        Map<String, String> payee = alipay.getPayee();
        AlipayClient alipayClient = new DefaultAlipayClient(payee.get("url"), payee.get("appid"), payee.get("private_key"), "json", "GBK", payee.get("alipay_public_key"), "RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        Map<String, String> map = new LinkedHashMap<>();
        map.put("out_trade_no", out_trade_no);
        map.put("trade_no", trade_no);
        map.put("refund_amount", "0.02");
        map.put("refund_reason", "正常退款");
        map.put("out_request_no", "HZ01RF001");
        map.put("operator_id", "OP001");
        map.put("store_id", "NJ_S_001");
        map.put("terminal_id", "NJ_T_001");

        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(map));

        request.setBizContent(jsonObject.toString());
        try {
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                System.out.println(response.toString());
                System.out.println("调用成功");
            } else {
                System.out.println("调用失败");
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    }

    //支付成功异步回调
    @PostMapping("/alipay_notify_url")
    public void alipay_notify_url(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
        log.info("接收到支付宝成回调。。。。。。。");
        Map<String, String> payee = alipay.getPayee();

        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = httpRequest.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            params.put(name, valueStr);
        }
        //乱码解决，这段代码在出现乱码时使用
        try {
            boolean signVerified = AlipaySignature.rsaCheckV1(params, payee.get("alipay_key"), "UTF-8", "RSA2"); //调用SDK验证签名
            log.info("aliReturnUrl().....params:" + params);
            log.info("aliReturnUrl().....signVerified:" + signVerified);
            if (signVerified) {//验证成功

                //商户订单号
                String out_trade_no = new String(httpRequest.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
                log.info("交易订单号out_trade_no：{}", out_trade_no);
                //支付宝交易号
                String trade_no = new String(httpRequest.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
                log.info("支付宝交易号trade_no：{}:", trade_no);
                //交易状态
                String trade_status = new String(httpRequest.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
                log.info("交易状态trade_status：{}:", trade_status);
                if (trade_status.equals("TRADE_FINISHED")) {
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //如果有做过处理，不执行商户的业务程序
                    //注意：
                    //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                } else if (trade_status.equals("TRADE_SUCCESS")) {
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //如果有做过处理，不执行商户的业务程序

                    //注意：
                    //付款完成后，支付宝系统发送该交易状态通知
                    Map<String, Object> map = new HashMap<>();
                    map.put("out_trade_no", new String(httpRequest.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"));
                    map.put("trade_no", new String(httpRequest.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"));
                    map.put("notify_time", new String(httpRequest.getParameter("notify_time").getBytes("ISO-8859-1"), "UTF-8"));
                    map.put("status", 1);

                    //调用支付宝分账功能 沙箱环境暂时将分账取消 TODO
                    subAccount(out_trade_no, trade_no);
                }
                //交易成功
                httpResponse.getWriter().println("success");


            } else {  //验证失败
                httpResponse.getWriter().println("fail");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void subAccount(String out_trade_no, String trade_no) {
        Map<String, String> payee = alipay.getPayee();
        Map<String, String> sub1 = alipay.getSub1();
        Map<String, String> sub2 = alipay.getSub2();

        AlipayClient alipayClient = new DefaultAlipayClient(payee.get("url"),
                payee.get("appid"),
                payee.get("private_key"),
                payee.get("format"),
                payee.get("charset"),
                payee.get("alipay_key"),
                payee.get("sign_type"));
        AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();

        //分账功能参数封装
        //保存参数插入
        List<Map<String, Object>> newList = new ArrayList<>();
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("out_request_no", out_trade_no);
        map.put("trade_no", trade_no);
        map.put("royalty_parameters", newList);

        //从口岸账户中分钱到伴行账户
        Map<String, Object> map1 = new LinkedHashMap<>();
        map1.put("trans_out", payee.get("pid"));
        map1.put("trans_in", sub1.get("pid"));
        map1.put("amount", "0.01");
        map1.put("desc", "分账给" + sub1.get("pid"));
        Map<String, Object> map2 = new LinkedHashMap<>();
        map2.put("trans_out", payee.get("pid"));
        map2.put("trans_in", sub2.get("pid"));
        map2.put("amount", "0.01");
        map2.put("desc", "分账给" + sub2.get("pid"));
        newList.add(map2);
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(map));
        log.info("subAccount()....." + jsonObject.toString());
        log.info("订单号:"+out_trade_no+","+payee.get("pid")+"分账给" + sub1.get("pid"));
        request.setBizContent(jsonObject.toString());
        try {
            AlipayTradeOrderSettleResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                log.info("subAccount()....." + response.getBody());
                //获取成功后的订单号
                log.info("调用成功");
            } else {
                System.err.println(response.getSubMsg());
                log.info("调用失败");
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    }


}
